package JDK常用类库.lambda;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * @author zx
 * @create 2023-07-31 23:38
 * Java内置的4大核心函数式接口
 * 消费型接口  Consumer<T>        void accept(T t)
 * 供给型接口  Supplier<T>        T get()
 * 函数型接口  Function<T,R>      R apply(T t)
 * 断定型接口  Predicate<T>       boolean test(T t)
 *
 */
public class LambdaTest2 {
    /**
     * 消费型接口：Consumer<T>
     * void accept(T t)：该方法接受一个参数并执行一些操作
     * 有参无返回值得接口, Consumer接口是用来消费数据的, 使用时需要指定一个泛型来定义参数类型
     */
    @Test
    public void test1(){
        happyTime(410, new Consumer<Double>() {
            @Override
            public void accept(Double d) {
                System.out.println("学习累了，可以找我聊天，别害羞！" + d);
            }
        });
        //自己写还是有点迷！
        happyTime(416, d -> System.out.println("学习累了，可以找我聊天，别矜持！" + d));
    }
    private void happyTime(double name, Consumer<Double> con){
        con.accept(name);
    }

    /**
     * 供给型接口  Supplier<T>
     * T get():该方法不接受任何参数并返回一个结果
     * 无参有返回值的接口，对于的Lambda表达式需要提供一个返回数据的类型。
     */
    @Test
    public void test2(){
        int arr[] = {22, 33, 55, 66, 44, 99, 10};
        // 计算出数组中的最大值
        fun(arr, new Supplier<Integer>() {
            @Override
            public Integer get() {
                Arrays.sort(arr);
                return arr[arr.length - 1];
            }
        });

        fun(arr, () -> {
            Arrays.sort(arr);
            return arr[arr.length - 1];
        });
    }
    private static void fun(int[] arr, Supplier<Integer> supplier){
        // get() 是一个无参的有返回值的抽象方法
        Integer max = supplier.get();
        System.out.println("max = " + max);
    }

    /**
     * 函数型接口  Function<T,R>
     * R apply(T t)：是 Function 接口的主要方法，它接收一个参数并返回一个结果。同时它也是唯一的抽象的方法
     * 有参有返回值的接口, Function接口是根据一个类型的数据得到另一个类型的数据, 前者称为前置条件, 后者称为后置条件
     */
    @Test
    public void test3(){
        add(new Function<String, Integer>() {
            @Override
            public Integer apply(String s) {
                return Integer.parseInt(s);
            }
        });

        add(msg -> {
            return Integer.parseInt(msg);
        });
    }
    private static void add(Function<String,Integer> function){
        Integer apply = function.apply("23") + 1;
        System.out.println("apply = " + apply);
    }

    /**
     * 断定型接口：Predicate<T>
     * test(T t)：该方法接受一个参数并返回一个布尔值
     * 有参且返回值为Boolean的接口。
     */
    @Test
    public void test4(){
        List<String> list = Arrays.asList("南京", "西安", "宝鸡", "未央区", "长安区", "江宁区", "千阳县");
        List<String> res = filterString(list, new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.contains("区");
            }
        });
        System.out.println(res);
        List<String> res1 = filterString(list, s -> s.contains("区"));
        System.out.println(res1);
    }
    //根据给定的规则，过滤集合中的字符串。此规则由Predicate的方法决定
    private List<String> filterString(List<String> list, Predicate<String> pre){
        ArrayList<String> filterList = new ArrayList<>();
        for(String s : list){
            if(pre.test(s)){
                filterList.add(s);
            }
        }
        return filterList;
    }
}
